/*
 *  Copyright 2012 yura.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */

package org.opu.pc.domain.impl;

import java.util.List;

import org.hibernate.SessionFactory;
import org.opu.pc.domain.SystemSettingsManagement;
import org.opu.pc.domain.SystemSettingsManagement.Option;
import org.opu.pc.domain.UserManagement;
import org.opu.pc.domain.dao.UserDao;
import org.opu.pc.domain.dao.impl.AbstractHibernateDao;
import org.opu.pc.domain.domains.security.SecurityGroup;
import org.opu.pc.domain.domains.security.SecurityGroupHolder;
import org.opu.pc.domain.domains.security.User;

import static org.opu.pc.domain.domains.security.SecurityGroup.*;
import org.opu.pc.util.Assert;
import org.springframework.dao.DataAccessException;
import org.springframework.security.authentication.encoding.PasswordEncoder;

public class UserManagementImpl implements UserManagement {

    private SystemSettingsManagement settingsManagement;
	private SessionFactory sessionFactory;
    private PasswordEncoder passwordEncoder;
	private UserDao userDao;

    public UserManagementImpl(SystemSettingsManagement settingsManagement,
            SessionFactory sessionFactory, PasswordEncoder passwordEncoder,
            UserDao userDao) {
        this.settingsManagement = settingsManagement;
        this.sessionFactory = sessionFactory;
        this.passwordEncoder = passwordEncoder;
        this.userDao = userDao;
    }
	
	@Override
	public void ensureDataRegistered(){
        AbstractHibernateDao<SecurityGroup, SecurityGroupHolder> absDao = 
                new AbstractHibernateDao<SecurityGroup, SecurityGroupHolder>() {

            @Override
            protected Class getDomainClass() {
                return SecurityGroupHolder.class;
            }
        };
        absDao.setSessionFactory(sessionFactory);
        if (absDao.get(Operator) == null)
            absDao.save(new SecurityGroupHolder(Operator));
        if (absDao.get(Secretary) == null)
            absDao.save(new SecurityGroupHolder(Secretary));
        if (absDao.get(Professor) == null)
            absDao.save(new SecurityGroupHolder(Professor));
		getGuestAccount();
	}

	@Override
	public List<User> list(){
        int id = settingsManagement.getInteger(Option.GuestUserId);
        final List<User> list = userDao.getList();
        Assert.True(list.remove(new User(id)));
		return list;
	}
	
	@Override
	public User getUser(Integer id){
		return userDao.get(id);
	}
	
	@Override
	public User getGuestAccount(){
        int id = settingsManagement.getInteger(Option.GuestUserId);
        User get = userDao.get(id);
        if (get == null){
            get = new User(null, UserDao.GuestAccountName, "", "");
            createUser(get);
            settingsManagement.setValue(Option.GuestUserId, get.getId());
        }
		return get;
	}
	
	@Override
	public void createUser(User user){
        user.setId(null);
        user.setPassword(encodePassword(user));
		userDao.save(user);
	}
	
	@Override
	public void updateUser(User bean){
		User get = userDao.get(bean.getId());
		get.setName(bean.getName());
        if (bean.getPassword() != null && !bean.getPassword().isEmpty()) {
            get.setPassword(encodePassword(bean));
        }
		get.setEmail(bean.getEmail());
        get.setSecurityGroups(bean.getSecurityGroups());
		userDao.saveOrUpdate(get);
	}

    @Override
    public void deleteUser(Integer id) {
        userDao.delete(userDao.get(id));
    }
	
	@Override
	public User getUserByName(String name){
		return userDao.getUserByName(name);
	}
	
	@Override
	public User getUserByNameAndPassword(String name, String pswd){
		return userDao.getUserByNameAndPassword(name, pswd);
	}

    @Override
    public User getNotGuestUserByName(String username) {
        int id = settingsManagement.getInteger(Option.GuestUserId);
        User user = userDao.getUserByName(username);
        if(user != null && id == user.getId()){
            return null;
        }
        return user;
    }

    private String encodePassword(User user) throws DataAccessException {
        return passwordEncoder.encodePassword(user.getPassword(), null);
    }
	
}
